/**
* All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
*
* MeetRecordService
* 会议纪要
*
* 修改纪录
* 2020-10-31 版本：1.0 donghang 创建。
* @version 版本：1.0
* @author 作者：donghang
* 创建日期：2020-10-31
*/
package com.topscomm.meet.service.impl;

import com.topscomm.base.BaseRemindTemplate;
import com.topscomm.base.BaseSystemConst;
import com.topscomm.base.pojo.BasePermissionManageEntity;
import com.topscomm.base.service.IBasePermissionManageService;
import com.topscomm.base.service.IBaseRemindTaskService;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.cbo.pojo.CboAttachmentEntity;
import com.topscomm.cbo.service.ICboAttachmentService;
import com.topscomm.cbo.service.ICboUserService;
import com.topscomm.meet.MeetSystemConst;
import com.topscomm.meet.MeetSystemConst.MeetPersonTypeEnum;
import com.topscomm.meet.MeetSystemConst.MeetStateEnum;
import com.topscomm.meet.pojo.MeetManageEntity;
import com.topscomm.meet.pojo.MeetRecordEntity;
import com.topscomm.meet.pojo.MeetTypeManageEntity;
import com.topscomm.meet.service.IMeetManageService;
import com.topscomm.meet.service.IMeetRecordService;
import com.topscomm.meet.service.IMeetTypeManageService;
import com.topscomm.meet.service.impl.auto.MeetRecordServiceAuto;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.common.DatacodeCache;
import com.topscomm.tap.common.ParameterCache;
import com.topscomm.tap.common.SessionUserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service(value = "meetRecordService")
@Scope(value = "singleton")
public class MeetRecordService extends MeetRecordServiceAuto implements IMeetRecordService {
	@Autowired
	private IBasePermissionManageService basePermissionManageService;
	@Autowired
	private IMeetTypeManageService meetTypeManageService;
	@Autowired
	private IMeetManageService meetManageService;
	@Autowired
	private ICboUserService cboUserService;
	@Autowired
	private IBaseRemindTaskService baseRemindTaskService;
	@Autowired
	private ICboAttachmentService cboAttachmentService;

	/**
	 * 保存会议数据
	 *
	 * @description:
	 * @param dataMap
	 * @param sessionUserBean
	 * @author: donghang
	 * @date: 2020年11月3日下午12:53:33
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public MeetRecordEntity save(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
		long id = ConvertUtil.convertToLong(dataMap.get("id"));
		MeetRecordEntity meetRecordEntity = new MeetRecordEntity();
		meetRecordEntity = (MeetRecordEntity) meetRecordEntity.convertFromMap(dataMap);
		if (id == 0) {
			// 纪要赋值id
			long[] arrayId = PrimaryKeyUtil.GeneIDs(MeetRecordEntity.tableName, 1);
			meetRecordEntity.setId(arrayId[0]);
			dataMap.put("id", arrayId[0]);
			// 通过会议表得到id，以免会议号重复
			arrayId = PrimaryKeyUtil.GeneIDs(MeetManageEntity.tableName, 1);
			long meetId = arrayId[0];
			String meetNum = String.valueOf(meetId);
			meetNum = meetNum.substring(0, 6) + meetNum.substring(9);
			meetRecordEntity.setMeetnum(meetNum);
			meetRecordEntity.setUsercode(sessionUserBean.getUser().getCode());
			meetRecordEntity.setUsername(sessionUserBean.getUser().getName());
			meetRecordEntity = this.insert(meetRecordEntity);
		} else {
			this.updateEntity(meetRecordEntity);
		}
		// 人员信息
		Map<String, Object> selectUsers = (Map<String, Object>) dataMap.get("selectUsers");
		List<BasePermissionManageEntity> userList = new ArrayList<>();
		String[] userTypes = { MeetPersonTypeEnum.Record, MeetPersonTypeEnum.Audio };
		for (String userType : userTypes) {
			List<BasePermissionManageEntity> tempList = this
					.getPermissionList((Map<String, Object>) selectUsers.get(userType), userType, sessionUserBean);
			if (tempList != null) {
				userList.addAll(tempList);
			}
		}
		basePermissionManageService.batchSaveList(String.valueOf(meetRecordEntity.getId()), MeetRecordEntity.tableName,
				userList);
		return meetRecordEntity;
	}

	/**
	 *
	 * @description:
	 * @param dataMap
	 * @param sessionUserBean
	 * @return
	 * @author: donghang
	 * @date: 2020年11月3日下午8:05:42
	 * @modify:
	 */

	private List<BasePermissionManageEntity> getPermissionList(Map<String, Object> dataMap, String type,
			SessionUserBean sessionUserBean) {
		List<BasePermissionManageEntity> userList = this.basePermissionManageService.processSelectUsers(dataMap, type,
				sessionUserBean.getUser().getCode(), sessionUserBean.getUser().getName());
		return userList;
	}

	/**
	 * 发布会议
	 *
	 * @description:
	 * @param dataMap
	 * @param sessionUserBean
	 * @author: donghang
	 * @date: 2020年11月3日上午9:19:34
	 * @modify: chengengwei
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void publish(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
		StringBufferProxy whereSql = new StringBufferProxy();
		// 记录更新之前状态
		int oldState = (int)dataMap.get(MeetRecordEntity.FieldState);
		// 会议记录id
		String id = ConvertUtil.convertToString(dataMap.get("id"));
		// 更新之前纪要授权人员
		whereSql.appendSingle(" sourcetype = '{0}' and sourceid = '{1}' and sourceflag = '{2}' ",
				MeetRecordEntity.tableName, id, MeetPersonTypeEnum.Record);
		List<BasePermissionManageEntity> oldRecordBasePermissionManageList = basePermissionManageService
				.queryByWhere(whereSql.toString());
		whereSql.clear();
		// 1.更新发布状态
		dataMap.put(MeetRecordEntity.FieldState, MeetStateEnum.Publish);
		MeetRecordEntity meetRecordEntity = this.save(dataMap, sessionUserBean);
		// 2.app通知相关人员，添加提醒配置，定点时间发送会议纪要，合并参会人、缺席人、纪要授权、录音授权
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendSingle(" 1=1 ");
		sql.appendSingle(" and sourceid='{0}' and sourcetype='{1}'", meetRecordEntity.getId(),
				MeetRecordEntity.tableName);
		// List<BasePermissionManageEntity> permissionList =
		// this.basePermissionManageService.queryByWhere(sql.toString());
		// 更新主表recorduploaded字段值为1，代表已经上传了会议纪要
		String meetid = ConvertUtil.convertToString(dataMap.get(MeetRecordEntity.FieldMeetid));
		if (!StringUtil.isEmpty(meetid) && !"0".equals(meetid)) {
			MeetManageEntity meetManageEntity = meetManageService.queryById(meetid);
			if (meetManageEntity != null) {
				meetManageEntity.setRecorduploaded(BaseSystemConst.CboYesNoEnum.Yes);
				meetManageService.updateEntity(meetManageEntity);
			}
			cn.hutool.core.thread.ThreadUtil.execAsync(() -> {
				try {
					// 根据meetRecordEntity发送消息提醒
					uploadRecordRemind(ConvertUtil.convertToString(meetManageEntity.getId()),
					MeetSystemConst.ReminUploadRecordSourceType, meetRecordEntity, oldState,
					oldRecordBasePermissionManageList);
				} catch (Exception e) {
					System.out.println("发送消息出错");
					e.printStackTrace();
					System.out.println(e.getMessage());
				}
			});
		} else { // 补录会议纪要发送消息提醒
			cn.hutool.core.thread.ThreadUtil.execAsync(() -> {
				try {
					// 根据meetRecordEntity发送消息提醒
					uploadRecordRemind(ConvertUtil.convertToString(meetRecordEntity.getId()),
					MeetSystemConst.ReminSupplementRecordSourceType, meetRecordEntity, oldState,
					oldRecordBasePermissionManageList);
				} catch (Exception e) {
					System.out.println("发送消息出错");
					e.printStackTrace();
					System.out.println(e.getMessage());
				}
			});
		}
	}

	/**
	 * @description: 发布会议资料后发送消息通知
	 * @author: chengengwei
	 * @date: 2021-03-29
	 * @modify:
	 */
	private void uploadRecordRemind(String sourceid, String sourcetype, MeetRecordEntity meetRecordEntity, int oldState,
									List<BasePermissionManageEntity> oldRecordBasePermissionManageList) {
		// 会议资料id
		long id = meetRecordEntity.getId();
		StringBufferProxy whereSql = new StringBufferProxy();
		// 消息推送人列表
		List<Map<String, Object>> allReminUserList = new ArrayList<>();
		// 授权人员
		whereSql.appendSingle(" sourcetype = '{0}' and sourceid = '{1}' and sourceflag = '{2}' ",
				MeetRecordEntity.tableName, id, MeetPersonTypeEnum.Record);
		List<BasePermissionManageEntity> newRecordBasePermissionManageList = basePermissionManageService
				.queryByWhere(whereSql.toString());
		whereSql.clear();
		// 若之前是暂存状态，则通知参会人员和纪要授权人员会议纪要已下发
		if (oldState == MeetStateEnum.Save) {
			Map<String, Object> basePermissionManageMap = processToMapUsers(newRecordBasePermissionManageList);
			// 授权人员
			allReminUserList = basePermissionManageService.getAllAttendUser(basePermissionManageMap);
			// 参会人员和缺席人员code
			allReminUserList.addAll(changeCodesToList(meetRecordEntity.getAttendusercodes()));
			allReminUserList.addAll(changeCodesToList(meetRecordEntity.getAbsentusercodes()));
			// 防止会议秘书与参会人员等重复
			allReminUserList = allReminUserList.stream().collect(Collectors.collectingAndThen(Collectors
					.toCollection(() -> new TreeSet<>(Comparator.comparing(map -> ConvertUtil
							.convertToString(map.get("id"))))), ArrayList::new));
		} else {
			// 若纪要授权人员发生变化，则提醒新增人员
			Map<String, Object> oldbasePermissionManageMap = processToMapUsers(oldRecordBasePermissionManageList);
			Map<String, Object> newbasePermissionManageMap = processToMapUsers(newRecordBasePermissionManageList);
			List<Map<String, Object>> oldAttendUser = basePermissionManageService
					.getAllAttendUser(oldbasePermissionManageMap);
			List<Map<String, Object>> newAttendUser = basePermissionManageService
					.getAllAttendUser(newbasePermissionManageMap);
			// 筛选出新增纪要授权人员
			for (Map<String, Object> newuser : newAttendUser) {
				boolean flag = true;
				for (Map<String, Object> olduser : oldAttendUser) {
					if (newuser.get("id").equals(olduser.get("id"))) flag = false;
				}
				if (flag) allReminUserList.add(newuser);
			}
		}
		// 发送消息提示
		if (allReminUserList.size() > 0) {
			// 消息主题
			String subject = BaseRemindTemplate.AppRemindTemplate.UploadRecordSubjectTemplate;
			// 拼接消息内容
			String content = String.format(BaseRemindTemplate.AppRemindTemplate.UploadRecordContentTemplate,
					ConvertUtil.convertToString(meetRecordEntity.getName()), meetRecordEntity.getLaunchorgname()
					+ "\\" + meetRecordEntity.getUsername());
			// 当前时间
			Date now = new Date();
			// 消息列表
			List<BasicEntity> pushList = new ArrayList<>();
			allReminUserList.forEach(user -> {
				pushList.add(createRemindTaskEntity(BaseSystemConst.BaseActionType.Create, sourceid, sourcetype, subject, content, now, ConvertUtil.convertToString(user.get("code")),ConvertUtil.convertToString(user.get("name"))));
			});
			// 插入消息
			baseRemindTaskService.insertBatch(pushList);
		}
	}

	private List<Map<String, Object>> changeCodesToList(String codes) {
		List<Map<String, Object>> userList = new ArrayList<>();
		StringBufferProxy whereSql = new StringBufferProxy();
		if (!StringUtil.isEmpty(codes)) {
			List<String> codesList = Arrays.asList(codes.split(","));
			// 防止大于1000项导致查询报错
			whereSql.appendSingle(" code in ( ");
			if (codesList.size() > 999) {
				for (int i = 0; i < codesList.size(); i++) {
					if (i % 999 == 0 && i > 0) {
						whereSql = whereSql.substring(0, whereSql.length() - 1);
						whereSql.appendSingle(" ) or code in ( '{1}',", codesList.get(i));
					} else {
						whereSql.appendSingle("'{0}',", codesList.get(i));
					}
				}
				whereSql = whereSql.substring(0, whereSql.length() - 1);
				whereSql.appendSingle(" )");
			} else {
				whereSql.appendSingle("'" + codesList.stream().collect(Collectors
						.joining("','")) + "' )");
			}
			userList = cboUserService.queryMapByWhere(whereSql.toString());
			whereSql.clear();
		}
		// 全部待通知人员
		return userList;
	}

	/**
	 * @description:将BasePermissionManage表的list转前台Map格式，支持多来源并去重
	 * @param list
	 * @return
	 * @author: chengengwei
	 * @date: 2021-2-24
	 * @modify:
	 */
	private Map<String, Object> processToMapUsers(List<BasePermissionManageEntity> list) {
		Map<String, Object> result = new HashMap<>();
		for (BasePermissionManageEntity basePermissionManageEntity : list) {
			if (BaseSystemConst.ShareTypeEnum.Dept.equals(basePermissionManageEntity.getSharetype())) {
				if (result.containsKey("deptcodes")) {
					result.put("deptcodes", result.get("deptcodes") + "," + basePermissionManageEntity.getShareobjects());
				} else {
					result.put("deptcodes", basePermissionManageEntity.getShareobjects());
				}
			} else if (BaseSystemConst.ShareTypeEnum.User.equals(basePermissionManageEntity.getSharetype())) {
				if (result.containsKey("usercodes")) {
					result.put("usercodes", result.get("usercodes") + "," + basePermissionManageEntity.getShareobjects());
				} else {
					result.put("usercodes", basePermissionManageEntity.getShareobjects());
				}
			} else if (BaseSystemConst.ShareTypeEnum.Role.equals(basePermissionManageEntity.getSharetype())) {
				if (result.containsKey("roleids")) {
					result.put("roleids", result.get("roleids") + "," + basePermissionManageEntity.getShareobjects());
				} else {
					result.put("roleids", basePermissionManageEntity.getShareobjects());
				}
			} else if (BaseSystemConst.ShareTypeEnum.Team.equals(basePermissionManageEntity.getSharetype())) {
				if (result.containsKey("teamids")) {
					result.put("teamids", result.get("teamids") + "," + basePermissionManageEntity.getShareobjects());
				} else {
					result.put("teamids", basePermissionManageEntity.getShareobjects());
				}
			} else if (BaseSystemConst.ShareTypeEnum.Share.equals(basePermissionManageEntity.getSharetype())) {
				if (result.containsKey("sharecodes")) {
					result.put("sharecodes", result.get("sharecodes") + "," + basePermissionManageEntity.getShareobjects());
				} else {
					result.put("sharecodes", basePermissionManageEntity.getShareobjects());
				}
			}
		}
		Set<String> tempSet = new HashSet<>();
		// 去重
		result.forEach((k, v) -> {
			String[] codes = ((String) v).split(",");
			tempSet.addAll(Arrays.asList(codes));
			result.put(k, tempSet.stream().collect(Collectors.joining(",")));
			tempSet.clear();
		});
		return result;
	}

	/**
	 * 取消会议
	 *
	 * @description:
	 * @param dataMap
	 * @param sessionUserBean
	 * @author: donghang
	 * @date: 2020年11月3日上午9:19:42
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancel(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
		// 1.更新取消状态
		dataMap.put(MeetManageEntity.FieldState, MeetStateEnum.Cancel);
		this.update(dataMap);
	}

	/**
	 * @description: 查询会议记录是否有附件或录音文件
	 * @author: chengengwei
	 * @date: 2021-04-12
	 * @modify:
	 */
	@Override
	public List<Map<String, Object>> queryRecordFileStateByIds(Map<String, Object> paraMap) {
		String ids = ConvertUtil.convertToString(paraMap.get("ids"));
		if (!StringUtil.isEmpty(ids)) {
			Map<String, Object> params = new HashMap<>();
			params.put("ids", ids);
			return this.queryMap(params, "queryRecordFileStateByIds");
		}
		return null;
	}

	/**
	 * @description: 设置用户不接收会议纪要消息提醒
	 * @author: chengengwei
	 * @date: 2021-05-31
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void setNotRemindUploadRecord(Map<String, Object> paraMap, SessionUserBean userBean) {
		String meetid = ConvertUtil.convertToString(paraMap.get("meetid"));
		String usercode = userBean.getUser().getCode();
		StringBufferProxy sql = new StringBufferProxy();
		String[] params = new String[]{MeetManageEntity.FieldNotremindusercode, "'" + usercode + ",'" };
		sql.appendSingle(" update MeetManage set {0} = {1} where id = {2} ",
				MeetManageEntity.FieldNotremindusercode, SQLAdapter.concat(params), meetid);
		this.meetManageService.updateExecute(sql.toString());
	}

	/**
	 *
	 * @description:
	 * @param mapRow
	 * @param datacodeCache
	 * @author: donghang
	 * @date: 2020年11月9日上午9:12:16
	 * @modify:
	 */
	public void setDispFields(Map<String, Object> mapRow, DatacodeCache datacodeCache) {
		super.setDispFields(mapRow, datacodeCache);
		String temp;
		if (mapRow.get("meettypeid") != null) {
			temp = mapRow.get("meettypeid").toString();
			String name = "", parentName = "";
			List<MeetTypeManageEntity> meetList = this.meetTypeManageService.queryByWhere("id=" + temp);
			if (meetList.size() == 1) {
				name = meetList.get(0).getName();
				if (meetList.get(0).getParentid() > 0) {
					List<MeetTypeManageEntity> parentList = this.meetTypeManageService
							.queryByWhere("id=" + meetList.get(0).getParentid());
					if (parentList.size() == 1) {
						parentName = parentList.get(0).getName();
					}
				}
			}
			if (parentName.length() > 0) {
				mapRow.put("dispmeettypeid", parentName + "/" + name);
			} else {
				mapRow.put("dispmeettypeid", name);
			}
		}
	}

	/**
	 * @description: 添加附件记录
	 * @author: chengengwei
	 * @date: 2021-08-30
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addAttachmentRecord(Map<String, Object> paraMap) {
		List<Map<String, Object>> records = (List)paraMap.get("records");
		String sourcetype = ConvertUtil.convertToString(paraMap.get("sourcetype"));
		String sourceid = ConvertUtil.convertToString(paraMap.get("sourceid"));
		// 先删除记录
		this.cboAttachmentService.deleteBySource(sourceid, sourcetype);
		List<BasicEntity> entities = new ArrayList<>();
		long typeId = ConvertUtil.convertToLong(ParameterCache.getValue(MeetSystemConst.RecordAttachmentTypeId, "0"));
		records.forEach(item -> {
			CboAttachmentEntity entity = new CboAttachmentEntity();
			entity.convertFromMap(item);
			entity.setAttachmenttypeid(typeId);
			entities.add(entity);
		});
		this.cboAttachmentService.insertBatch(entities);
	}
}
